/*
  * File:		pbd_pblock.h
  * Purpose:	Packet block handlers. A packet is divided by protocol and organized in
  * 			blocks. You can create packet block, append packet content, remove block...
  * Author:	yoyo
  * Date:	2011-6-24
  */

#ifndef _PBD_PBLOCK_H
#define _PBD_PBLOCK_H

#include "pbd_type.h"

typedef struct pbd_pblock{
	uint8 *data;		// packet block data
	int len;		// block data total size
	int clen;		// current data size
	int layer;		// block data belong to which layer
/* tcp/ip network layer
     each layer using id 1~100
  */
#define PBD_LAYER_1	100
#define PBD_LAYER_2	200
#define PBD_LAYER_3 300
#define PBD_LAYER_4 400
#define PBD_LAYER_5 500
// more clear classify, start from 100
#define PBD_LAYER_1P5 150
#define PBD_LAYER_2P5 250
// undefined layer
#define PBD_LAYER_NONE 0
	int type;		// block data protocol type
#define PBD_PBLOCK_ETH	0x1
#define PBD_PBLOCK_ARP	0x100// 0x0806
#define PBD_PBLOCK_RARP	0x101// 0x8035
#define PBD_PBLOCK_IPV4	0x102// 0x0800
#define PBD_PBLOCK_IPV6	0x103// 0x86dd
	int id;		// indicate block sequence in same layer

	struct pbd_pblock *prev;
	struct pbd_pblock *next;
}pbd_pblock_t;

#define PBLOCK_ITER(pblock_head, pblock)	\
	for (pblock = (pblock_head)->next; pblock; pblock = pblock->next)	

/*
  * Append packet block context with buf. It would not create new pblock, but
  * add content of 'pblock'.
  * @pblock - packet block to append content
  * @buf - data to append
  * @buflen - data length
  * Return 1 if success, otherwise return -1
  */
int pbd_pblock_append(pbd_pblock_t *pblock, uint8 *buf, int buflen);

/*
  * Add new packet block in the list of pblock. pblocks are organized by [layer, id].
  * Each pblock assigned the smallest id which is not used in that layer.
  * @pblock_head - head of list
  * @pblock - packet block to add
  * Return 1 if success, otherwise return -1
  */
int pbd_pblock_add(pbd_pblock_t *pblock_head, pbd_pblock_t *pblock);

/*
  * Remove packet block 'pblock' from the list of pblock.
  * @pblock_head - head of list
  * @pblock - packet block to add
  * Return 1 if success, otherwise return -1
  */
int pbd_pblock_rem(pbd_pblock_t *pblock_head, pbd_pblock_t *pblock);

/*
  * Remove packet block 'pblock' from the list of pblock. Safe in iterator scan
  * @pblock_head - head of list
  * @pblock - packet block to add
  * Return 1 if success, otherwise return -1
  */
int pbd_pblock_rem_itr(pbd_pblock_t *pblock_head, pbd_pblock_t *pblock);

/*
  * Create new packet block and return it
  * @size - new pblock data size
  * @layer - pblock layer, see defines in struct pbd_pblock
  * @type - pblock type, see defines in struct pbd_pblock
  * @buf - pblock data
  * @buflen - pblock data size
  * Return pblock if create success, otherwise return NULL
  */
pbd_pblock_t *pbd_pblock_new(int size, int layer, int type, uint8 *buf, int buflen);

/*
  * Free packet block
  * @pblock - pblock to free
  */
void pbd_pblock_free(pbd_pblock_t *pblock);

/*
  * Get together pblock content and organized in a real packet form, and
  * then return the packet
  * @pblock_head - pblock head
  * @size - packet size
  * Return packet if success, otherwise return NULL
  */
uint8 *pbd_pblock_gather(pbd_pblock_t *pblock_head, int *size);

#endif

